package org.lbm.flow.engine;

import org.lbm.flow.context.FlowContext;
import org.lbm.flow.node.Node;
import org.lbm.flow.node.NodeResult;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.Collections;

/**
 * 工作流执行引擎
 *
 * @author insist
 * @since 2025-08-01
 * 负责管理工作流的执行流程
 */
public class FlowEngine {

    private final Map<String, Node> nodes;
    private final Map<String, NodeResult> nodeResults;
    private final ExecutorService executor;
    private final FlowContext context;
    private final String flowId;

    private volatile boolean running = false;
    private volatile boolean cancelled = false;

    public FlowEngine(String flowId) {
        this.flowId = flowId;
        this.nodes = new ConcurrentHashMap<>();
        this.nodeResults = new ConcurrentHashMap<>();
        this.executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        this.context = new FlowContext(flowId);
    }

    /**
     * 添加节点
     */
    public FlowEngine addNode(Node node) {
        nodes.put(node.getId(), node);
        return this;
    }

    /**
     * 添加节点并建立连接
     */
    public FlowEngine addNode(Node node, List<String> predecessors, List<String> successors) {
        addNode(node);

        if (predecessors != null) {
            for (String predId : predecessors) {
                node.addPredecessor(predId);
            }
        }

        if (successors != null) {
            for (String succId : successors) {
                node.addSuccessor(succId);
            }
        }

        return this;
    }

    /**
     * 连接两个节点
     */
    public FlowEngine connect(String fromNodeId, String toNodeId) {
        Node fromNode = nodes.get(fromNodeId);
        Node toNode = nodes.get(toNodeId);

        if (fromNode == null) {
            throw new IllegalArgumentException("源节点不存在: " + fromNodeId);
        }
        if (toNode == null) {
            throw new IllegalArgumentException("目标节点不存在: " + toNodeId);
        }

        fromNode.addSuccessor(toNodeId);
        toNode.addPredecessor(fromNodeId);

        return this;
    }

    /**
     * 执行工作流
     */
    public FlowResult execute() {
        if (running) {
            throw new IllegalStateException("工作流正在执行中");
        }

        running = true;
        cancelled = false;
        long startTime = System.currentTimeMillis();

        System.out.println("开始执行工作流: " + flowId);

        try {
            // 找到所有起始节点（没有前置节点的节点）
            List<Node> startNodes = findStartNodes();

            if (startNodes.isEmpty()) {
                return FlowResult.failed(flowId, "没有找到起始节点");
            }

            // 执行起始节点
            List<CompletableFuture<NodeResult>> futures = new ArrayList<>();
            for (Node startNode : startNodes) {
                CompletableFuture<NodeResult> future = executeNodeAsync(startNode);
                futures.add(future);
            }

            // 等待所有起始节点完成
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

            // 检查是否有节点失败
            for (CompletableFuture<NodeResult> future : futures) {
                NodeResult result = future.get();
                if (result.isFailed()) {
                    return FlowResult.failed(flowId, "节点执行失败: " + result.getNodeId() + " - " + result.getMessage());
                }
            }

            // 继续执行后续节点
            executeRemainingNodes();

            long executionTime = System.currentTimeMillis() - startTime;
            System.out.println("工作流执行完成，耗时: " + executionTime + "ms");

            return FlowResult.success(flowId, nodeResults)
                    .withExecutionTime(executionTime);

        } catch (Exception e) {
            long executionTime = System.currentTimeMillis() - startTime;
            System.err.println("工作流执行异常: " + e.getMessage());
            e.printStackTrace();
            return FlowResult.failed(flowId, "执行异常: " + e.getMessage(), e)
                    .withExecutionTime(executionTime);
        } finally {
            running = false;
        }
    }

    /**
     * 异步执行节点
     */
    private CompletableFuture<NodeResult> executeNodeAsync(Node node) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                if (cancelled) {
                    return NodeResult.cancelled(node.getId(), "工作流已取消");
                }

                NodeResult result = node.execute(context);
                nodeResults.put(node.getId(), result);

                return result;
            } catch (Exception e) {
                NodeResult result = NodeResult.failed(node.getId(), "执行异常: " + e.getMessage(), e);
                nodeResults.put(node.getId(), result);
                return result;
            }
        }, executor);
    }

    /**
     * 执行后续节点
     */
    private void executeSuccessors(Node node) {
        for (String successorId : node.getSuccessors()) {
            Node successor = nodes.get(successorId);
            if (successor != null && successor.canExecute(context)) {
                executeNodeAsync(successor);
            }
        }
    }

    /**
     * 执行剩余节点
     */
    private void executeRemainingNodes() {
        List<Node> executableNodes = findExecutableNodes();

        while (!executableNodes.isEmpty() && !cancelled) {
            List<CompletableFuture<NodeResult>> futures = new ArrayList<>();

            for (Node node : executableNodes) {
                CompletableFuture<NodeResult> future = executeNodeAsync(node);
                futures.add(future);
            }

            // 等待当前批次完成
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

            // 检查是否有节点失败
            for (CompletableFuture<NodeResult> future : futures) {
                try {
                    NodeResult result = future.get();
                    if (result.isFailed()) {
                        return; // 有节点失败，停止执行
                    }
                } catch (Exception e) {
                    return; // 有异常，停止执行
                }
            }

            // 查找下一批可执行节点
            executableNodes = findExecutableNodes();
        }
    }

    /**
     * 查找起始节点
     */
    private List<Node> findStartNodes() {
        List<Node> startNodes = new ArrayList<>();
        for (Node node : nodes.values()) {
            if (node.getPredecessors().isEmpty() && node.canExecute(context)) {
                startNodes.add(node);
            }
        }
        return startNodes;
    }

    /**
     * 查找可执行节点
     */
    private List<Node> findExecutableNodes() {
        List<Node> executableNodes = new ArrayList<>();
        for (Node node : nodes.values()) {
            if (!nodeResults.containsKey(node.getId()) && node.canExecute(context)) {
                executableNodes.add(node);
            }
        }
        return executableNodes;
    }

    /**
     * 取消工作流执行
     */
    public void cancel() {
        cancelled = true;
        System.out.println("工作流执行已取消");
    }

    /**
     * 获取工作流上下文
     */
    public FlowContext getContext() {
        return context;
    }

    /**
     * 获取节点结果
     */
    public Map<String, NodeResult> getNodeResults() {
        return new HashMap<>(nodeResults);
    }

    /**
     * 获取节点
     */
    public Node getNode(String nodeId) {
        return nodes.get(nodeId);
    }

    /**
     * 获取所有节点
     */
    public Map<String, Node> getNodes() {
        return new HashMap<>(nodes);
    }

    /**
     * 获取按拓扑顺序排列的节点ID列表
     */
    public List<String> getTopologicalOrder() {
        List<String> result = new ArrayList<>();
        Set<String> visited = new HashSet<>();
        Set<String> temp = new HashSet<>();

        // 找到所有起始节点
        List<Node> startNodes = findStartNodes();
        for (Node node : startNodes) {
            topologicalSort(node.getId(), visited, temp, result);
        }

        // 反转结果，使其按照正确的执行顺序排列
        Collections.reverse(result);
        return result;
    }

    /**
     * 拓扑排序的递归实现
     */
    private void topologicalSort(String nodeId, Set<String> visited, Set<String> temp, List<String> result) {
        if (temp.contains(nodeId)) {
            throw new RuntimeException("检测到循环依赖: " + nodeId);
        }
        if (visited.contains(nodeId)) {
            return;
        }

        temp.add(nodeId);
        Node node = nodes.get(nodeId);
        if (node != null) {
            for (String successorId : node.getSuccessors()) {
                topologicalSort(successorId, visited, temp, result);
            }
        }
        temp.remove(nodeId);
        visited.add(nodeId);
        result.add(nodeId);
    }

    /**
     * 关闭引擎
     */
    public void shutdown() {
        executor.shutdown();
    }

    /**
     * 检查是否正在运行
     */
    public boolean isRunning() {
        return running;
    }

    /**
     * 检查是否已取消
     */
    public boolean isCancelled() {
        return cancelled;
    }
}
